package com.rfid.reader;

import java.io.IOException;

public class R2000Reader extends RfidReader {
	private final static byte START_RSP_FLAG = (byte)0xBB;
	private final static byte START_CMD_FLAG = (byte)0xAA;
	
	private final static byte RFID_CMD_TAG_NOTIFY = (byte)0x10;
	private final static byte RFID_CMD_STOP_INVETORY = (byte) 0x31;
	private final static byte RFID_CMD_START_INVENTORY = (byte) 0x32;
	private final static byte RFID_CMD_RESET_DEVICE = (byte)0x65;
	private byte[] readerId = null;
	

	public R2000Reader() {
		readerId = new byte[2];
		readerId[0] = 0;
		readerId[1] = 0;
	}
	private void BuildMessageHeader(byte commandCode) {
		// TODO Auto-generated method stub
		sendIndex = 0;
		sendMsgBuff[sendIndex++] = START_CMD_FLAG;
		sendMsgBuff[sendIndex++] = 0;
		sendMsgBuff[sendIndex++] = 0;
		sendMsgBuff[sendIndex++] = readerId[0];
		sendMsgBuff[sendIndex++] = readerId[1];
		sendMsgBuff[sendIndex++] = commandCode;
	}
	
	private byte CaculateCheckSum(byte []message,int start_pos,int len)
	{
		long checksum = 0;
		int iIndex = 0;
		for (iIndex = 0;iIndex < len; iIndex++)
		{
			checksum += getUnsignedByte(message[start_pos+iIndex]);
		}
		checksum = ~checksum + 1;
		return (byte)(checksum & 0xFF);
	}
	
	private void FillLengthAndCheksum() {
		sendMsgBuff[1] = 0;
		sendMsgBuff[2] = (byte)(sendIndex - 2);
		sendMsgBuff[sendIndex] = CaculateCheckSum(sendMsgBuff, 0, sendIndex);
		++sendIndex;
	}
	
	@Override
	public int Inventory() throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_START_INVENTORY);
		FillLengthAndCheksum();
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int InventoryOnce() throws IOException {
		// TODO Auto-generated method stub
		System.out.println("Now R2000 does not support this function.");
		return -1;
	}

	@Override
	public int Stop() throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_STOP_INVETORY);
		FillLengthAndCheksum();
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int Reset() throws IOException {
		// TODO Auto-generated method stub
		BuildMessageHeader(RFID_CMD_RESET_DEVICE);
		FillLengthAndCheksum();
		transport.SendData(sendMsgBuff, sendIndex);
		return 0;
	}

	@Override
	public int RelayControl(int relayNo, int operation, int time) throws IOException {
		return 0;
	}

	@Override
	public int ReadTagBlock(byte membank,byte addr,byte len,byte[] accessPassword) throws IOException{
		// TODO Auto-generated method stub
		System.out.println("Now R2000 does not support this function.");
		return -1;
	}

	@Override
	public int WriteTagBlock(byte membank,int addr,byte len, byte[] writtenData,int writeStartIndex,byte[] accessPassword) throws IOException{
		// TODO Auto-generated method stub
		System.out.println("Now R2000 does not support this function.");
		return -1;
	}

	@Override
	public int LockTag(byte lockType,byte[] accessPassword) throws IOException{
		// TODO Auto-generated method stub
		System.out.println("Now R2000 does not support this function.");
		return -1;
	}

	@Override
	public int KillTag(byte[] accessPassword,byte[] killPassword) throws IOException{
		// TODO Auto-generated method stub
		System.out.println("Now R2000 does not support this function.");
		return -1;
	}

	@Override
	public int HandleRecv() throws IOException {
		// TODO Auto-generated method stub
		recvMsgLen = transport.ReadData(recvMsgBuff);
		HandleMessage();
		return 0;
	}

	@Override
	public void HandleMessage() {
		// TODO Auto-generated method stub
		byte []message = recvMsgBuff;
		byte checksum = 0;
		byte caculatedChecksum = 0;
		int buffPos = 0;
		int rspLen = 0;
		while (buffPos <= recvMsgLen - 7){
			if ( message[buffPos] != START_RSP_FLAG)
			{
				buffPos++;
			}
			
			rspLen = getUnsignedByte(message[buffPos+1]);
			rspLen = rspLen << 8;
			rspLen = rspLen += getUnsignedByte(message[buffPos+2]);
			if (rspLen > 255) {
				buffPos++;
				continue;
			}
			
			checksum = message[buffPos + rspLen + 2];
			caculatedChecksum = CaculateCheckSum(message,buffPos,rspLen+2);
			if (caculatedChecksum == checksum)
			{
				NotifyMessageToApp(message, buffPos);
				buffPos = buffPos + rspLen + 3;
			}
			else {
				++buffPos;
			}
		}
	}

	@Override
	protected void NotifyMessageToApp(byte[] message, int startIndex) {
		// TODO Auto-generated method stub
		AppNotify appNotify = getAppNotify();
		if ( null == appNotify) {
			return;
		}
		switch(message[startIndex + 5]) {
		case RFID_CMD_STOP_INVETORY:
			appNotify.NotifyStopInventory(message, startIndex);
			break;
		case RFID_CMD_RESET_DEVICE:
			appNotify.NotifyReset(message, startIndex);
			break;
		case RFID_CMD_START_INVENTORY:
			appNotify.NotifyStartInventory(message, startIndex);
			break;
		case RFID_CMD_TAG_NOTIFY:
			appNotify.NotifyRecvTags(message, startIndex);
			break;
			default:
				break;
		}
	}

}
